<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>霓虹冲刺：核心过载 - 完整 Demo</title>
    <style>
        /* --- CSS 样式 --- */
        body { margin: 0; overflow: hidden; font-family: 'Orbitron', sans-serif; background: #000; }
        
        /* 通用 UI 容器 */
        .screen {
            position: absolute; top: 0; left: 0; width: 100%; height: 100%;
            display: flex; flex-direction: column; justify-content: center; align-items: center;
            color: #fff; text-align: center; user-select: none;
        }
        /* 隐藏状态 */
        .hidden { display: none !important; }

        /* 主菜单和结束画面样式 */
        .overlay-bg { background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(5px); }
        h1 {
            font-size: 60px; margin-bottom: 20px; color: #00f7ff;
            text-shadow: 0 0 20px #00f7ff, 0 0 40px #00aaff;
            letter-spacing: 5px;
        }
        h2 { font-size: 30px; color: #ff0055; text-shadow: 0 0 10px #ff0055; }
        p { font-size: 18px; color: #ccc; }
        
        /* 按钮样式 */
        .btn {
            padding: 15px 40px; font-size: 24px; color: #fff;
            background: transparent; border: 3px solid #00f7ff;
            box-shadow: 0 0 15px #00f7ff inset, 0 0 15px #00f7ff;
            cursor: pointer; transition: all 0.3s; margin-top: 30px;
            text-transform: uppercase;
        }
        .btn:hover { background: #00f7ff; color: #000; box-shadow: 0 0 30px #00f7ff; }

        /* --- 游戏中 HUD --- */
        #hud {
            position: absolute; top: 20px; left: 20px; right: 20px;
            display: flex; justify-content: space-between; pointer-events: none;
        }
        .hud-item { font-size: 24px; color: #00f7ff; text-shadow: 0 0 5px #00f7ff; }
        /* 血条样式 */
        #health-bar { display: flex; gap: 5px; }
        .health-point {
            width: 30px; height: 15px; background: #ff0055;
            box-shadow: 0 0 10px #ff0055; transform: skewX(-20deg);
        }
        .health-lost { background: #330011; box-shadow: none; }

    </style>
    <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>

    <div id="main-menu" class="screen overlay-bg">
        <h1>NEON RUSH</h1>
        <p>核心过载 // Core Overload</p>
        <p style="margin-top: 40px; font-size: 14px;">移动鼠标控制方向，避开红色能量柱</p>
        <button id="start-btn" class="btn">启动引擎</button>
    </div>

    <div id="game-hud" class="screen hidden" style="justify-content: flex-start; align-items: flex-start;">
        <div id="hud">
            <div id="health-container">
                HEALTH: 
                <div id="health-bar">
                    <div class="health-point"></div>
                    <div class="health-point"></div>
                    <div class="health-point"></div>
                </div>
            </div>
            <div>SCORE: <span id="score-counter">0</span></div>
        </div>
    </div>

    <div id="game-over" class="screen overlay-bg hidden">
        <h2>SYSTEM FAILURE</h2>
        <h1>GAME OVER</h1>
        <p>最终得分: <span id="final-score" style="color:#00f7ff; font-size: 30px;">0</span></p>
        <button id="restart-btn" class="btn">重启系统</button>
    </div>

    <div id="container"></div>


    <script type="importmap">
        {
            "imports": {
                "three": "https://unpkg.com/three@0.160.0/build/three.module.js"
            }
        }
    </script>

    <script type="module">
        import * as THREE from 'three';

        // ===========================
        // 1. 全局变量与配置
        // ===========================
        let scene, camera, renderer, player;
        let obstacles = [];
        let gridHelper, starMesh;

        // 游戏状态
        let gameState = "MENU"; // "MENU", "PLAYING", "GAMEOVER"
        
        // 游戏数值
        let score = 0;
        let health = 3;
        let baseSpeed = 0.5;
        let currentSpeed = baseSpeed;
        let frameCount = 0;
        let isInvincible = false; // 无敌状态（受伤后短暂）

        // UI 元素引用
        const mainMenu = document.getElementById('main-menu');
        const gameHud = document.getElementById('game-hud');
        const gameOverScreen = document.getElementById('game-over');
        const scoreCounter = document.getElementById('score-counter');
        const finalScoreDisplay = document.getElementById('final-score');
        const healthPoints = document.querySelectorAll('.health-point');
        const startBtn = document.getElementById('start-btn');
        const restartBtn = document.getElementById('restart-btn');

        // 鼠标控制
        const mouse = new THREE.Vector2();
        const targetPos = new THREE.Vector3();


        // ===========================
        // 2. 初始化 Three.js 场景
        // ===========================
        function init() {
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0x0a0a14);
            scene.fog = new THREE.Fog(0x0a0a14, 20, 60);

            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(0, 3, 8);

            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMap.enabled = true;
            document.getElementById('container').appendChild(renderer.domElement);

            // 灯光
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
            scene.add(ambientLight);
            const dirLight = new THREE.DirectionalLight(0x00f7ff, 1.5);
            dirLight.position.set(5, 10, 7);
            dirLight.castShadow = true;
            scene.add(dirLight);

            // 环境元素
            createWorld();
            // 玩家
            createPlayer();

            // 事件监听
            window.addEventListener('resize', onWindowResize);
            document.addEventListener('mousemove', onMouseMove);
            startBtn.addEventListener('click', startGame);
            restartBtn.addEventListener('click', resetGame);

            animate();
        }

        function createWorld() {
            // 地面网格
            gridHelper = new THREE.GridHelper(150, 75, 0x00f7ff, 0x222244);
            scene.add(gridHelper);

            // 幽灵地面 (接收阴影)
            const planeGeo = new THREE.PlaneGeometry(200, 200);
            const planeMat = new THREE.ShadowMaterial({ opacity: 0.5 });
            const plane = new THREE.Mesh(planeGeo, planeMat);
            plane.rotation.x = -Math.PI / 2;
            plane.position.y = -0.1;
            plane.receiveShadow = true;
            scene.add(plane);

            // 星空粒子
            const starsGeo = new THREE.BufferGeometry();
            const starsCount = 800;
            const posArray = new Float32Array(starsCount * 3);
            for(let i = 0; i < starsCount * 3; i++) {
                posArray[i] = (Math.random() - 0.5) * 150;
            }
            starsGeo.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
            const starsMat = new THREE.PointsMaterial({size: 0.15, color: 0x00f7ff, transparent: true, opacity: 0.8});
            starMesh = new THREE.Points(starsGeo, starsMat);
            scene.add(starMesh);
        }

        function createPlayer() {
            // 玩家设计：一个主体方块加上两个侧翼
            const bodyGeo = new THREE.BoxGeometry(1, 0.8, 1.5);
            const wingGeo = new THREE.BoxGeometry(0.4, 0.4, 1);

            // 材质：使用 MeshPhongMaterial 以获得更好的高光
            const playerMat = new THREE.MeshPhongMaterial({ 
                color: 0x00f7ff, 
                emissive: 0x004466,
                shininess: 100
            });

            player = new THREE.Group();
            
            const body = new THREE.Mesh(bodyGeo, playerMat);
            body.castShadow = true;
            player.add(body);

            const leftWing = new THREE.Mesh(wingGeo, playerMat);
            leftWing.position.set(-0.8, 0, -0.2);
            player.add(leftWing);

            const rightWing = new THREE.Mesh(wingGeo, playerMat);
            rightWing.position.set(0.8, 0, -0.2);
            player.add(rightWing);
            
            player.position.set(0, 0.5, 0);
            scene.add(player);
        }

        function createObstacle() {
            // 障碍物：旋转的能量柱
            const height = Math.random() * 3 + 2; // 随机高度
            const geo = new THREE.CylinderGeometry(0.4, 0.4, height, 8);
            const mat = new THREE.MeshPhongMaterial({ 
                color: 0xff0055, 
                emissive: 0x550022,
                shininess: 50,
                flatShading: true // 低多边形风格
            }); 
            const mesh = new THREE.Mesh(geo, mat);
            
            // 随机 X 位置 (-6 到 6)
            mesh.position.x = (Math.random() - 0.5) * 12;
            mesh.position.y = height / 2; // 确保底部贴地
            mesh.position.z = -80 - (currentSpeed * 10); // 根据速度调整生成距离
            
            mesh.castShadow = true;
            
            // 给障碍物一个随机旋转速度属性
            mesh.userData.rotSpeedX = Math.random() * 0.05;
            mesh.userData.rotSpeedY = Math.random() * 0.05 + 0.02;

            scene.add(mesh);
            obstacles.push(mesh);
        }

        // ===========================
        // 3. 游戏流程控制
        // ===========================
        function startGame() {
            gameState = "PLAYING";
            mainMenu.classList.add('hidden');
            gameHud.classList.remove('hidden');
            score = 0;
            health = 3;
            currentSpeed = baseSpeed;
            frameCount = 0;
            isInvincible = false;
            updateUI();
            // 重置相机位置
            camera.position.set(0, 3, 8);
            camera.lookAt(0,0,0);
        }

        function endGame() {
            gameState = "GAMEOVER";
            gameHud.classList.add('hidden');
            gameOverScreen.classList.remove('hidden');
            finalScoreDisplay.innerText = score;
        }

        function resetGame() {
            gameOverScreen.classList.add('hidden');
            // 清除障碍物
            obstacles.forEach(obj => scene.remove(obj));
            obstacles = [];
            player.position.set(0, 0.5, 0);
            // 恢复玩家材质颜色（如果死在红色状态）
            player.children.forEach(mesh => mesh.material.emissive.setHex(0x004466));

            startGame();
        }

        function updateUI() {
            scoreCounter.innerText = score;
            // 更新血条视觉
            healthPoints.forEach((point, index) => {
                if (index < health) {
                    point.classList.remove('health-lost');
                } else {
                    point.classList.add('health-lost');
                }
            });
        }

        function playerHit() {
            if (isInvincible) return;

            health--;
            updateUI();
            
            if (health <= 0) {
                endGame();
            } else {
                // 受伤效果：变红并短暂无敌
                isInvincible = true;
                player.children.forEach(mesh => mesh.material.emissive.setHex(0xff0000));
                
                setTimeout(() => {
                    isInvincible = false;
                    player.children.forEach(mesh => mesh.material.emissive.setHex(0x004466));
                }, 800); // 800ms 无敌时间
            }
        }


        // ===========================
        // 4. 事件处理
        // ===========================
        function onMouseMove(event) {
            if (gameState !== "PLAYING") return;
            // 归一化鼠标坐标
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            // 映射到游戏世界宽度
            targetPos.x = mouse.x * 7; 
        }

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }

        // ===========================
        // 5. 核心动画循环 (Game Loop)
        // ===========================
        function animate() {
            requestAnimationFrame(animate);

            // --- A. 菜单/结束状态的背景动画 ---
            if (gameState !== "PLAYING") {
                // 缓慢旋转场景增加动感
                scene.rotation.y += 0.002;
                starMesh.rotation.z += 0.0005;
                gridHelper.position.z = (gridHelper.position.z + 0.1) % 10;
                renderer.render(scene, camera);
                return; // 如果不是 playing，就只渲染背景动画，不执行游戏逻辑
            }

            // --- B. 游戏进行中逻辑 ---
            
            // 重置场景旋转（从菜单状态恢复）
            scene.rotation.y = 0;

            frameCount++;

            // 1. 难度提升 (速度随分数增加)
            currentSpeed = baseSpeed + (score * 0.0005);
            // 限制最大速度
            currentSpeed = Math.min(currentSpeed, 1.2);

            // 2. 玩家移动 (平滑插值)
            player.position.x += (targetPos.x - player.position.x) * 0.15;
            // 倾斜效果
            player.rotation.z = (player.position.x - targetPos.x) * 0.15;
            // 前进颠簸效果
            player.position.y = 0.5 + Math.sin(frameCount * 0.2) * 0.05;

            // 3. 障碍物生成 (生成频率随速度提高)
            let spawnRate = Math.floor(50 - currentSpeed * 20);
            spawnRate = Math.max(spawnRate, 15); // 最小间隔 15 帧
            if (frameCount % spawnRate === 0) {
                createObstacle();
            }

            // 4. 环境动画
            gridHelper.position.z = (gridHelper.position.z + currentSpeed) % 10;
            starMesh.rotation.z += 0.002 * currentSpeed;
            starMesh.position.z += currentSpeed * 0.5;
            if (starMesh.position.z > 50) starMesh.position.z = 0;


            // 5. 障碍物逻辑循环
            for (let i = obstacles.length - 1; i >= 0; i--) {
                const obj = obstacles[i];
                
                // 移动
                obj.position.z += currentSpeed;
                // 自转
                obj.rotation.x += obj.userData.rotSpeedX;
                obj.rotation.z += obj.userData.rotSpeedY;

                // 碰撞检测 (简单的距离检测)
                // 考虑到玩家和障碍物都不是完美球体，距离阈值需要微调
                const collisionThreshold = 1.2; 
                // 只检测 Z 轴接近的，避免远处误判
                if (Math.abs(obj.position.z - player.position.z) < 1.0) {
                     const dist = player.position.distanceTo(obj.position);
                     if (dist < collisionThreshold) {
                        playerHit();
                        // 撞击后移除该障碍物，避免连续判定
                        scene.remove(obj);
                        obstacles.splice(i, 1);
                        continue; 
                    }
                }

                // 超出屏幕移除并加分
                if (obj.position.z > 10) {
                    scene.remove(obj);
                    obstacles.splice(i, 1);
                    score++;
                    updateUI();
                }
            }

            renderer.render(scene, camera);
        }

        // 启动！
        init();

    </script>
</body>
</html>